home *** CD-ROM | disk | FTP | other *** search
/ Complete Linux / Complete Linux.iso / docs / apps / database / postgres / postgre4.z / postgre4 / src / utils / cache / syscache.c < prev   
Encoding:
C/C++ Source or Header  |  1992-08-27  |  17.2 KB  |  691 lines

  1. /* ----------------------------------------------------------------
  2.  *   FILE
  3.  *    syscache.c
  4.  *    
  5.  *   DESCRIPTION
  6.  *    System cache management routines
  7.  *
  8.  *   INTERFACE ROUTINES
  9.  *    SearchSysCacheTuple()
  10.  *    SearchSysCacheStruct()
  11.  *    SearchSysCacheGetAttribute()
  12.  *    TypeDefaultRetrieve()
  13.  *
  14.  *   NOTES
  15.  *    These routines allow the parser/planner/executor to perform
  16.  *    rapid lookups on the contents of the system catalogs.  (Well,
  17.  *    mabey not so rapid just yet..)
  18.  *
  19.  *    see lib/catalog/syscache.h for a list of the cache id's
  20.  *
  21.  * old notes:
  22.  *    LISP code should call SearchSysCacheStruct with preallocated space
  23.  *     (or SearchSysCacheGetAttribute for variable-length or system fields).
  24.  *    C code should call SearchSysCacheTuple -- it's slightly more efficient.
  25.  *
  26.  *   IDENTIFICATION
  27.  *    $Header: /private/postgres/src/utils/cache/RCS/syscache.c,v 1.26 1992/06/10 05:05:00 mer Exp $
  28.  * ----------------------------------------------------------------
  29.  */
  30. #include "tmp/c.h"
  31.  
  32. RcsId("$Header: /private/postgres/src/utils/cache/RCS/syscache.c,v 1.26 1992/06/10 05:05:00 mer Exp $");
  33.  
  34. #include "access/heapam.h"
  35. #include "access/htup.h"
  36. #include "catalog/catname.h"
  37. #include "utils/catcache.h"
  38. #include "utils/log.h"
  39. #include "utils/palloc.h"
  40. #include "nodes/pg_lisp.h"
  41.  
  42. /* ----------------
  43.  *    hardwired attribute information comes from system catalog files.
  44.  * ----------------
  45.  */
  46. #include "catalog/pg_am.h"
  47. #include "catalog/pg_amop.h"
  48. #include "catalog/pg_attribute.h"
  49. #include "catalog/pg_index.h"
  50. #include "catalog/pg_inherits.h"
  51. #include "catalog/pg_language.h"
  52. #include "catalog/pg_opclass.h"
  53. #include "catalog/pg_operator.h"
  54. #include "catalog/pg_proc.h"
  55. #include "catalog/pg_prs2rule.h"
  56. #include "catalog/pg_prs2plans.h"
  57. #include "catalog/pg_prs2stub.h"
  58. #include "catalog/pg_relation.h"
  59. #include "catalog/pg_type.h"
  60. #include "catalog/pg_rewrite.h"
  61. #include "catalog/pg_aggregate.h"
  62. #include "catalog/pg_naming.h"
  63. #include "utils/large_object.h"
  64. #include "catalog/pg_lobj.h"
  65. #include "catalog/pg_listener.h"
  66.  
  67. extern bool    AMI_OVERRIDE;    /* XXX style */
  68.  
  69. #define BIGENDIAN        /* e.g.: 68000, MIPS, Tahoe */
  70. /*#define LITTLEENDIAN        /* e.g.: VAX, i386 */
  71.  
  72. #include "catalog/syscache.h"
  73. #include "catalog/indexing.h"
  74.     
  75. /* ----------------
  76.  *    Warning:  cacheinfo[] below is changed, then be sure and
  77.  *    update the magic constants in syscache.h!
  78.  *
  79.  *    Note: currently all the catalog cache index names are
  80.  *    NULL.  This will change soon -cim 1/13/91.
  81.  * ----------------
  82.  */
  83. static struct cachedesc cacheinfo[] = {
  84.     { &AccessMethodOperatorRelationName,    /* AMOPOPID */
  85.       2,
  86.       { AccessMethodOperatorOperatorClassIdAttributeNumber,
  87.         AccessMethodOperatorOperatorIdAttributeNumber,
  88.         0,
  89.         0 },
  90.       sizeof(struct amop),
  91.       NULL,
  92.       NULL  },
  93.     { &AccessMethodOperatorRelationName,    /* AMOPSTRATEGY */
  94.       3,
  95.       { AccessMethodOperatorAccessMethodIdAttributeNumber,
  96.         AccessMethodOperatorOperatorClassIdAttributeNumber,
  97.         AccessMethodOperatorStrategyAttributeNumber,
  98.         0 },
  99.       sizeof(struct amop),
  100.       NULL,
  101.       NULL  },
  102.     { &AttributeRelationName,            /* ATTNAME */
  103.       2,
  104.       { AttributeRelationIdAttributeNumber,
  105.         AttributeNameAttributeNumber,
  106.         0,
  107.         0 },
  108.       sizeof(struct attribute),
  109.       &AttributeNameIndex,
  110.       AttributeNameIndexScan  },
  111.     { &AttributeRelationName,            /* ATTNUM */
  112.       2,
  113.       { AttributeRelationIdAttributeNumber,
  114.         AttributeNumberAttributeNumber,
  115.         0,
  116.         0 },
  117.       sizeof(struct attribute),
  118.       &AttributeNumIndex,
  119.       AttributeNumIndexScan  },
  120.     { &IndexRelationName,            /* INDEXRELID */
  121.       1,
  122.       { IndexRelationIdAttributeNumber,
  123.         0,
  124.         0,
  125.         0 },
  126.       sizeof(struct index),
  127.       NULL,
  128.       NULL  },
  129.     { &LanguageRelationName,            /* LANNAME */
  130.       1,
  131.       { LanguageNameAttributeNumber,
  132.         0,
  133.         0,
  134.         0 },
  135.       sizeof(struct language) - sizeof(struct varlena),
  136.       NULL,
  137.       NULL  },
  138.     { &OperatorRelationName,            /* OPRNAME */
  139.       4,
  140.       { OperatorNameAttributeNumber,
  141.         OperatorLeftAttributeNumber,
  142.         OperatorRightAttributeNumber,
  143.         OperatorKindAttributeNumber },
  144.       sizeof(struct operator),
  145.       NULL,
  146.       NULL  },
  147.     { &OperatorRelationName,            /* OPROID */
  148.       1,
  149.       { ObjectIdAttributeNumber,
  150.         0,
  151.         0,
  152.         0 },
  153.       sizeof(struct operator),
  154.       NULL,
  155.       NULL  },
  156.     { &ProcedureRelationName,            /* PRONAME */
  157.       1,
  158.       { ProcedureNameAttributeNumber,
  159.         0,
  160.         0,
  161.         0 },
  162.       sizeof(struct proc),
  163.       &ProcedureNameIndex,
  164.       ProcedureNameIndexScan  },
  165.     { &ProcedureRelationName,            /* PROOID */
  166.       1,
  167.       { ObjectIdAttributeNumber,
  168.         0,
  169.         0,
  170.         0 },
  171.       sizeof(struct proc),
  172.       &ProcedureOidIndex,
  173.       ProcedureOidIndexScan  },
  174.     { &RelationRelationName,            /* RELNAME */
  175.       1,
  176.       { RelationNameAttributeNumber,
  177.         0,
  178.         0,
  179.         0 },
  180.       sizeof(struct relation),
  181.       NULL,
  182.       NULL  },
  183.     { &RelationRelationName,            /* RELOID */
  184.       1,
  185.       { ObjectIdAttributeNumber,
  186.         0,
  187.         0,
  188.         0 },
  189.       sizeof(struct relation),
  190.       NULL,
  191.       NULL  },
  192.     { &TypeRelationName,            /* TYPNAME */
  193.       1,
  194.       { TypeNameAttributeNumber,
  195.         0,
  196.         0,
  197.         0 },
  198.       sizeof(TypeTupleFormData) - sizeof(struct varlena),
  199.       &TypeNameIndex,
  200.       TypeNameIndexScan  },
  201.     { &TypeRelationName,            /* TYPOID */
  202.       1,
  203.       { ObjectIdAttributeNumber,
  204.         0,
  205.         0,
  206.         0},
  207.       sizeof(TypeTupleFormData) - sizeof(struct varlena),
  208.       &TypeOidIndex,
  209.       TypeOidIndexScan  },
  210.     { &AccessMethodRelationName,        /* AMNAME */
  211.       1,
  212.       { AccessMethodNameAttributeNumber,
  213.         0,
  214.         0,
  215.         0},
  216.       sizeof(IndexTupleFormData),
  217.       NULL,
  218.       NULL  },
  219.     { &OperatorClassRelationName,        /* CLANAME */
  220.       1,
  221.       { OperatorClassNameAttributeNumber,
  222.         0,
  223.         0,
  224.         0},
  225.       sizeof(IndexTupleFormData),
  226.       NULL,
  227.       NULL  },
  228.     { &IndexRelationName,            /* INDRELIDKEY */
  229.       2,
  230.       { IndexHeapRelationIdAttributeNumber,
  231.         IndexKeyAttributeNumber,
  232.         0,
  233.         0},
  234.       sizeof(IndexTupleFormData),
  235.       NULL,
  236.       NULL  },
  237.     { &InheritsRelationName,            /* INHRELID */
  238.       2,
  239.       { InheritsRelationIdAttributeNumber,
  240.         InheritsSequenceNumberAttributeNumber,
  241.         0,
  242.         0},
  243.       sizeof(InheritsTupleFormD),
  244.       NULL,
  245.       NULL  },
  246.     { &Prs2PlansRelationName,            /* PRS2PLANCODE */
  247.       2,
  248.       { Prs2PlansRuleIdAttributeNumber,
  249.         Prs2PlansPlanNumberAttributeNumber,
  250.         0,
  251.         0 },
  252.       sizeof(struct prs2plans) - sizeof(struct varlena),
  253.       NULL,
  254.       NULL  },
  255.     { &RewriteRelationName,            /* RULOID */
  256.       1,
  257.       { ObjectIdAttributeNumber,
  258.         0,
  259.         0,
  260.         0 },
  261.       sizeof(FormData_pg_rewrite),
  262.       NULL,
  263.       NULL  },
  264.     { &Prs2StubRelationName,            /* PRS2STUB */
  265.       2,
  266.       { Anum_pg_prs2stub_prs2relid,
  267.         Anum_pg_prs2stub_prs2no,
  268.         0,
  269.         0 },
  270.       sizeof(FormData_pg_prs2stub) - sizeof(struct varlena),
  271.       NULL,
  272.       NULL  },
  273.     { &Prs2RuleRelationName,            /* PRS2RULEID    */
  274.       1,
  275.       { Anum_pg_prs2rule_prs2name,
  276.         0,
  277.         0,
  278.         0 },
  279.       sizeof(FormData_pg_prs2rule),
  280.       NULL,
  281.       NULL  },
  282.     { &Prs2RuleRelationName,            /* PRS2EVENTREL    */
  283.       1,
  284.       { ObjectIdAttributeNumber,
  285.         0,
  286.         0,
  287.         0 },
  288.       sizeof(FormData_pg_prs2rule),
  289.       NULL,
  290.       NULL  },
  291.     { &AggregateRelationName,            /*AGGNAME*/
  292.       1,
  293.       { AggregateNameAttributeNumber,
  294.             0,
  295.         0,
  296.         0 },
  297.        sizeof(FormData_pg_aggregate),
  298.        NULL,
  299.        NULL  },    
  300.     { &NamingRelationName,                      /*NAMEREL */
  301.         2,
  302.         { Anum_pg_naming_parent_oid,/*NamingParentOIDAttributeNumber,*/
  303.             Anum_pg_naming_filename,/*NamingFilenameAttributeNumber,*/
  304.             0,
  305.             0 },
  306.         sizeof(FormData_pg_naming),
  307.         NULL,
  308.     NULL  },
  309.     { &LargeObjectAssocRelationName,           /*LOBJREL */
  310.         1,
  311.         { Anum_pg_large_object_oid,/*LargeObjectOIDAttributeNumber,*/
  312.             0,
  313.             0,
  314.             0 },
  315.         sizeof (FormData_pg_large_object),
  316.         NULL,
  317.     NULL  },
  318.     { &ListenerRelationName,                  /* LISTENREL */
  319.     2,
  320.     {  Anum_pg_listener_relname,
  321.          Anum_pg_listener_pid,
  322.          0,
  323.          0 },
  324.     sizeof(FormData_pg_listener),
  325.     NULL,
  326.     NULL  }
  327. };
  328.  
  329. static struct catcache    *SysCache[lengthof(cacheinfo)];
  330. static int32        SysCacheSize = lengthof(cacheinfo);
  331.     
  332.     
  333. /*
  334.  *    zerocaches
  335.  *
  336.  *    Make sure the SysCache structure is zero'd.
  337.  */
  338. zerocaches()
  339. {
  340.     bzero((char *) SysCache, SysCacheSize * sizeof(struct catcache *));
  341. }
  342.  
  343. /*
  344.  * Note:
  345.  *    This function was written because the initialized catalog caches
  346.  *    are used to determine which caches may contain tuples which need
  347.  *    to be invalidated in other backends.
  348.  */
  349. void
  350. InitCatalogCache()
  351. {
  352.     int    cacheId;    /* XXX type */
  353.     
  354.     if (!AMI_OVERRIDE) {
  355.     for (cacheId = 0; cacheId < SysCacheSize; cacheId += 1) {
  356.         
  357.         Assert(!PointerIsValid((Pointer)SysCache[cacheId]));
  358.         
  359.         SysCache[cacheId] =
  360.         InitSysCache((*cacheinfo[cacheId].name)->data, 
  361.                  cacheinfo[cacheId].indname,
  362.                  cacheinfo[cacheId].nkeys,
  363.                  cacheinfo[cacheId].key,
  364.                  cacheinfo[cacheId].iScanFunc);
  365.         if (!PointerIsValid((char *)SysCache[cacheId])) {
  366.         elog(WARN,
  367.              "InitCatalogCache: Can't init cache %.16s(%d)",
  368.              (*cacheinfo[cacheId].name)->data,
  369.              cacheId);
  370.         }
  371.         
  372.         /* XXX the cacheId should be passed in InitSysCache */
  373.         CatalogCacheSetId(SysCache[cacheId], cacheId);
  374.     }
  375.     }
  376. }
  377.  
  378. /*
  379.  *    SearchSysCacheTuple
  380.  *
  381.  *    A layer on top of SearchSysCache that does the initialization and
  382.  *    key-setting for you.
  383.  *
  384.  *    Returns the tuple if one is found, NULL if not.
  385.  *
  386.  *    XXX The tuple that is returned is NOT supposed to be pfree'd!
  387.  */
  388.  
  389. /**** xxref:
  390.  *           getmyrelids
  391.  *           GetAttributeRelationIndexRelationId
  392.  *           SearchSysCacheStruct
  393.  *           SearchSysCacheGetAttribute
  394.  *           TypeDefaultRetrieve
  395.  ****/
  396. HeapTuple
  397. SearchSysCacheTuple(cacheId, key1, key2, key3, key4)
  398.     int        cacheId;        /* cache selection code */
  399.     char    *key1, *key2, *key3, *key4;
  400. {
  401.     register HeapTuple    tp;
  402.     
  403.     if (cacheId < 0 || cacheId >= SysCacheSize) {
  404.     elog(WARN, "SearchSysCacheTuple: Bad cache id %d", cacheId);
  405.     return((HeapTuple) NULL);
  406.     }
  407.     
  408.     if (!AMI_OVERRIDE) {
  409.     Assert(PointerIsValid(SysCache[cacheId]));
  410.     } else {
  411.     if (!PointerIsValid(SysCache[cacheId])) {
  412.         SysCache[cacheId] =
  413.         InitSysCache((*cacheinfo[cacheId].name)->data, 
  414.                  cacheinfo[cacheId].indname,
  415.                  cacheinfo[cacheId].nkeys,
  416.                  cacheinfo[cacheId].key,
  417.                  cacheinfo[cacheId].iScanFunc);
  418.         if (!PointerIsValid(SysCache[cacheId])) {
  419.         elog(WARN,
  420.              "InitCatalogCache: Can't init cache %.16s(%d)",
  421.              (*cacheinfo[cacheId].name)->data,
  422.              cacheId);
  423.         }
  424.         
  425.         /* XXX the cacheId should be passed in InitSysCache */
  426.         CatalogCacheSetId(SysCache[cacheId], cacheId);
  427.     }
  428.     }
  429.     
  430.     tp = SearchSysCache(SysCache[cacheId], key1, key2, key3, key4);
  431.     if (!HeapTupleIsValid(tp)) {
  432. #ifdef CACHEDEBUG
  433.     elog(DEBUG,
  434.          "SearchSysCacheTuple: Search %s(%d) %d %d %d %d failed", 
  435.          (*cacheinfo[cacheId].name)->data,
  436.          cacheId, key1, key2, key3, key4);
  437. #endif
  438.     return((HeapTuple) NULL);
  439.     }
  440.     return(tp);
  441. }
  442.  
  443. /*
  444.  *    SearchSysCacheStruct
  445.  *
  446.  *    Fills 's' with the information retrieved by calling SearchSysCache()
  447.  *    with arguments key1...key4.  Retrieves only the portion of the tuple
  448.  *    which is not variable-length.
  449.  *
  450.  *    NOTE: we are assuming that non-variable-length fields in the system
  451.  *          catalogs will always be defined!
  452.  *
  453.  *    Returns 1L if a tuple was found, 0L if not.
  454.  */
  455.  
  456. int32
  457. SearchSysCacheStruct(cacheId, returnStruct, key1, key2, key3, key4)
  458.     int        cacheId;        /* cache selection code */
  459.     char    *returnStruct;        /* return struct (preallocated!) */
  460.     char    *key1, *key2, *key3, *key4;
  461. {
  462.     HeapTuple    tp;
  463.     
  464.     if (!PointerIsValid(returnStruct)) {
  465.     elog(WARN, "SearchSysCacheStruct: No receiving struct");
  466.     return(0);
  467.     }
  468.     tp = SearchSysCacheTuple(cacheId, key1, key2, key3, key4);
  469.     if (!HeapTupleIsValid(tp))
  470.     return(0);
  471.     bcopy((char *) GETSTRUCT(tp), returnStruct, cacheinfo[cacheId].size);
  472.     return(1);
  473. }
  474.  
  475.  
  476. /*
  477.  *    SearchSysCacheGetAttribute
  478.  *
  479.  *    Returns the attribute corresponding to 'attributeNumber' for
  480.  *    a given cached tuple.
  481.  *
  482.  *    XXX This re-opens a relation, so this is slower.
  483.  */
  484. /**** xxref:
  485.  *           TypeDefaultRetrieve
  486.  ****/
  487. LispValue
  488. SearchSysCacheGetAttribute(cacheId, attributeNumber, key1, key2, key3, key4)
  489.     int            cacheId;
  490.     AttributeNumber    attributeNumber;
  491.     char         *key1, *key2, *key3, *key4;
  492. {
  493.     HeapTuple    tp;
  494.     char    *cacheName;
  495.     Relation    relation;
  496.     int32    attributeLength, attributeByValue;
  497.     Boolean    isNull;
  498.     char    *attributeValue;
  499.     LispValue    returnValue;
  500.     
  501.     tp = SearchSysCacheTuple(cacheId, key1, key2, key3, key4);
  502.     cacheName = (*cacheinfo[cacheId].name)->data;
  503.     
  504.     if (!HeapTupleIsValid(tp)) {
  505. #ifdef    CACHEDEBUG
  506.     elog(DEBUG,
  507.          "SearchSysCacheGetAttribute: Lookup in %s(%d) failed",
  508.          cacheName, cacheId);
  509. #endif    /* defined(CACHEDEBUG) */
  510.     return(LispNil);
  511.     }
  512.     
  513.     relation = heap_openr(cacheName);
  514.     
  515.     if (attributeNumber < 0 &&
  516.     attributeNumber > FirstLowInvalidHeapAttributeNumber) {
  517.     attributeLength = heap_sysattrlen(attributeNumber);
  518.     attributeByValue = heap_sysattrbyval(attributeNumber);
  519.     } else if (attributeNumber > 0 &&
  520.            attributeNumber <= relation->rd_rel->relnatts) {
  521.     attributeLength =
  522.         relation->rd_att.data[attributeNumber-1]->attlen;
  523.     attributeByValue =
  524.         relation->rd_att.data[attributeNumber-1]->attbyval;
  525.     } else {
  526.     elog(WARN, 
  527.          "SearchSysCacheGetAttribute: Bad attr # %d in %s(%d)",
  528.          attributeNumber, cacheName, cacheId);
  529.     return(LispNil);
  530.     }
  531.     
  532.     attributeValue = heap_getattr(tp,
  533.                   (Buffer) 0,
  534.                   attributeNumber,
  535.                   &relation->rd_att,
  536.                   &isNull);
  537.     
  538.     if (isNull) {
  539.     /*
  540.      * Used to be an elog(DEBUG, ...) here and a claim that it should
  541.      * be a FATAL error, I don't think either is warranted -mer 6/9/92
  542.      */
  543.     return(LispNil);
  544.     }
  545.     
  546.     LISP_GC_OFF;
  547.     
  548.     if (attributeByValue) {
  549.     returnValue = lispInteger((int) attributeValue);
  550.     } else {
  551.     char    *tmp;
  552.     int size = (attributeLength < 0)
  553.         ? VARSIZE((struct varlena *) attributeValue) /* variable length */
  554.         : attributeLength;                 /* fixed length */
  555.     
  556.     tmp = (char *) palloc(size);
  557.     bcopy(attributeValue, tmp, size);
  558.     returnValue = (LispValue)tmp;
  559.     }
  560.     
  561.     LISP_GC_PROTECT(returnValue);
  562.     LISP_GC_ON;
  563.     
  564.     heap_close(relation);
  565.     return(returnValue);
  566. }
  567.  
  568. /*
  569.  * DANGER!!!  Bizarre byte-ordering hacks follow.-hirohama
  570.  *                (nest ten miles) -jc
  571.  */
  572. /*
  573.  *    TypeDefaultRetrieve
  574.  *
  575.  *    Given a type OID, return the typdefault field associated with that
  576.  *    type.  The typdefault is returned as the car of a dotted pair which
  577.  *    is passed to TypeDefaultRetrieve by the calling routine.
  578.  *
  579.  *    Returns a fixnum for types which are passed by value and a ppreserve'd
  580.  *    vectori for types which are not.
  581.  */
  582. /**** xxref:
  583.  *           <apparently-unused>
  584.  ****/
  585. LispValue
  586. TypeDefaultRetrieve(typId)
  587.     ObjectId        typId;
  588. {
  589.     HeapTuple        typeTuple;
  590.     TypeTupleForm    type;
  591.     int32        typByVal, typLen;
  592.     struct varlena    *typDefault;
  593.     int32        dataSize;
  594.     LispValue        returnValue;
  595.     
  596.     typeTuple = SearchSysCacheTuple(TYPOID,
  597.                     (char *) typId,
  598.                     (char *) NULL,
  599.                     (char *) NULL,
  600.                     (char *) NULL);
  601.     
  602.     if (!HeapTupleIsValid(typeTuple)) {
  603. #ifdef    CACHEDEBUG
  604.     elog(DEBUG, "TypeDefaultRetrieve: Lookup in %s(%d) failed",
  605.          (*cacheinfo[TYPOID].name)->data, TYPOID);
  606. #endif    /* defined(CACHEDEBUG) */
  607.     return(LispNil);
  608.     }
  609.     
  610.     type = (TypeTupleForm) GETSTRUCT(typeTuple);
  611.     typByVal = type->typbyval;
  612.     typLen = type->typlen;
  613.     
  614.     typDefault = (struct varlena *)
  615.     SearchSysCacheGetAttribute(TYPOID, 
  616.                    TypeDefaultAttributeNumber,
  617.                    (char *) typId,
  618.                    (char *) NULL,
  619.                    (char *) NULL,
  620.                    (char *) NULL);
  621.     
  622.     if (typDefault == (struct varlena *)NULL) {
  623. #ifdef    CACHEDEBUG
  624.     elog(DEBUG, "TypeDefaultRetrieve: No extractable typdefault",
  625.          (*cacheinfo[TYPOID].name)->data, TYPOID);
  626. #endif    /* defined(CACHEDEBUG) */
  627.     return(LispNil);
  628.     
  629.     }
  630.     
  631.     dataSize = VARSIZE(typDefault) - sizeof(typDefault->vl_len);
  632.     
  633.     /*
  634.      * If the attribute is passed by value, copy the data bytes left to
  635.      * right into the return structure.  Otherwise, copy the entire struct
  636.      * varlena (which works out to be the same as ppreserve()'ing the
  637.      * vl_dat portion).
  638.      *
  639.      * XXX This is garbage.  The varlena should contain the external form,
  640.      *     which should be converted using fmgr() -- it would be easier
  641.      *     to specify and maintain that way.  But nooooo...catalogs have
  642.      *     to contain internal form attributes....
  643.      */
  644.     LISP_GC_OFF;
  645.     
  646.     if (typByVal) {
  647.     int32    aligned = 0;
  648.     
  649.     if (dataSize == typLen) {
  650.         bcopy(VARDATA(typDefault),
  651.           /* 
  652.            * The data itself is assumed to be the correct
  653.            * byte-order; however, which end we copy the
  654.            * bytes into does depend on the processor...
  655.            */
  656.           
  657. #ifdef LITTLEENDIAN
  658.           /* flush-left for little-endian (LSB..MSB) */
  659.           (char *) &aligned,
  660. #else /* !LITTLEENDIAN */
  661. #ifdef BIGENDIAN                  
  662.           /* flush-right for big-endian (MSB..LSB) */
  663.           ((char *) &aligned) + (sizeof(aligned) -
  664.                      dataSize),
  665. #else /* !BIGENDIAN */
  666.           /* you've got one, you figure it out... */
  667. #endif /* !BIGENDIAN */
  668. #endif /* !LITTLEENDIAN */
  669.           (int) dataSize);
  670.         
  671.         returnValue = lispInteger((int) aligned);
  672.     } else {
  673.         returnValue = LispNil;
  674.     }
  675.     } else {
  676.     if ((typLen < 0 && dataSize < 0) || dataSize != typLen)
  677.         returnValue = LispNil;
  678.     else {
  679.         returnValue = lispVectori(VARSIZE(typDefault));
  680.         bcopy((char *) typDefault,
  681.           (char *) LISPVALUE_BYTEVECTOR(returnValue),
  682.           (int) VARSIZE(typDefault));
  683.     }
  684.     }
  685.     
  686.     LISP_GC_PROTECT(returnValue);
  687.     LISP_GC_ON;
  688.     return(returnValue);
  689. }
  690.  
  691.